<template>
  <div class="file-upload-container">
    <div v-if="mode === 'DESIGN'">
      <a-button type="primary" shape="round">
        <template #icon>
          <icon-plus />
        </template>
        选择文件
      </a-button>
      <div v-ellipsis="{ rows: 1, text: `${placeholder}${sizeTip}` }"></div>
    </div>
    <div class="file-list-box" v-else>
      <a-upload
        v-if="!$attrs.disabled && _value.length < maxNumber"
        :file-list="_value"
        :show-file-list="false"
        multiple
        :limit="maxNumber"
        :on-before-upload="beforeUpload"
        :custom-request="customUpload"
        @exceed-limit="oneExceed"
        @error="onError"
      >
        <template #upload-button>
          <a-button type="primary" shape="round">
            <template #icon>
              <icon-plus />
            </template>
            选择文件
          </a-button>
        </template>
      </a-upload>
      <div v-if="!$attrs.disabled" v-ellipsis="{ rows: 1, text: `${placeholder}${sizeTip}` }"></div>
      <div class="file-list">
        <div class="file-list__item" v-for="(item, index) in _value as any" :key="item.fileId">
          <div class="item-filename">
            <div class="item-filename__label one-ellipsis" @click="handelDownload(item)">{{ item.fileName }}</div>
            <div v-if="!$attrs.disabled" class="item-filename__del" @click="handleRemove(index)">x</div>
          </div>
          <a-progress
            v-if="fileUploadComplete.loadingArr[item.fileId] !== 100"
            size="medium"
            :percent="fileUploadComplete.loadingArr[item.fileId]"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, useAttrs } from "vue";
import { Message } from "@arco-design/web-vue";
import type { FileItem, RequestOption } from "@arco-design/web-vue";
import { isEmpty } from "lodash";
import { createNewFilename } from "@/utils/upload";
import { generateId } from "@/utils";
import useMultipartOssStore from "@/stores/modules/multipartOssStore";
import useFileUploadComplete from "@/stores/modules/fileUploadComplete";

const $attrs = useAttrs();
const props = defineProps({
  modelValue: {
    type: Array,
    default: () => []
  },
  mode: {
    type: String,
    default: "DESIGN"
  },
  required: {
    type: Boolean,
    default: false
  },
  readonly: {
    type: Boolean,
    default: false
  },
  maxSize: {
    type: Number,
    default: 5
  },
  maxNumber: {
    type: Number,
    default: 20
  },

  placeholder: {
    type: String,
    default: "请选择附件"
  },
  fileTypes: {
    type: Array,
    default: () => {
      return [];
    }
  }
});
const emit = defineEmits(["update:modelValue"]);
const multipartOssStore = useMultipartOssStore();
const fileUploadComplete = useFileUploadComplete();

const sizeTip = computed(() => {
  if (props.fileTypes.length > 0) {
    return ` | 只允许上传[${String(props.fileTypes).replaceAll(",", "、")}]格式的文件，且单个附件不超过${props.maxSize}MB`;
  }
  return props.maxSize > 0 ? ` | 单个附件不超过${props.maxSize}MB` : "";
});
const _value = computed({
  get() {
    if (props.modelValue?.length) {
      props.modelValue.forEach((item: any) => {
        fileUploadComplete.setFileLoading(item.fileId, 100);
      });
    }
    return Array.isArray(props.modelValue) ? props.modelValue : [];
  },
  set(val) {
    emit("update:modelValue", val);
  }
});

const beforeUpload = (file: File) => {
  if (props.maxSize <= 0) {
    Message.error("请设置正确的文件大小！");
    return false;
  }
  const maxSize = file.size / 1024 / 1024 < props.maxSize;
  if (!maxSize) {
    Message.error(`单个文件大小不能超过${props.maxSize}M!`);
    return false;
  }
  return true;
};
const oneExceed = () => {
  Message.error(`最多上传${props.maxNumber}个文件`);
  return false;
};
const onError = (fileItem: FileItem) => {
  alert(`onError:${JSON.stringify(fileItem)}`);
  console.log("onError>>>", fileItem);
};

const fileToBlob = (fileItem: FileItem) => {
  const { uid: fileId, file } = fileItem;
  return {
    fileId,
    fileName: file?.name,
    name: file?.name,
    size: file?.size,
    type: file?.type,
    fileUrl: URL.createObjectURL(file as File)
  };
};
const customUpload = async (option: RequestOption) => {
  try {
    const { uid: fileId = generateId(), file } = option.fileItem;
    _value.value.push(fileToBlob(option.fileItem));
    fileUploadComplete.setFileLoading(fileId, 0);
    const { file: fileData, objectName } = await createNewFilename(file);
    await multipartOssStore.submit(objectName, fileData, fileId);
    await multipartOssStore.setACL(objectName, "public-read");
    const fileUrl = await multipartOssStore.signatureUrl(objectName);
    fileUploadComplete.setCompleteState(fileId, true);
    const url = fileUrl ? fileUrl.split("?")[0] : "";
    const fileObj = {
      fileUrl: url,
      url,
      fileId,
      fileName: fileData.name
    };
    const index = _value.value.findIndex((item: any) => item.fileId === fileId);
    index !== -1 && (_value.value[index] = { ...fileObj });
    emit("update:modelValue", _value.value);
  } catch (err) {
    console.log(err);
    alert(`文件上传错误：${JSON.stringify(err)}`);
  }
};
const handelDownload = (item: any) => {
  window.open(item.fileUrl);
};
const handleRemove = (index: number) => {
  _value.value.splice(index, 1);
};

if (isEmpty(_value.value) && !$attrs.disabled) {
  _value.value = $attrs.defaultValue as any[];
}
</script>

<style lang="scss" scoped>
$text-color-regular: #606266;
.file-upload-container {
  width: 100%;
}
.one-ellipsis {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-list-box {
  width: 100%;
  :deep(.kl-trigger) {
    font-size: 12px;
    color: #606266;
    margin-top: 7px;
  }
}
.file-list {
  width: 100%;
  margin: 10px auto;
  &__item {
    cursor: pointer;
    margin-bottom: 5px;
    font-size: 14px;

    .item-filename {
      @include flex-between;
      align-items: center;
      margin-bottom: 1px;
      &__label {
        width: 95%;
        color: $text-color-regular;
      }
      &__del {
        @include flex-inline-flex;
        width: 20px;
        height: 20px;
        border-radius: 50%;

        &:hover {
          background-color: rgba(0, 0, 0, 0.2);
        }
      }
    }
  }
}
</style>
